
package com.dlc.shop.common.allinpay.util;

import com.dlc.shop.common.allinpay.bean.OpException;
import com.dlc.shop.common.config.Constant;
import jakarta.validation.constraints.NotNull;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.io.FileInputStream;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.Enumeration;
import java.util.Locale;
/**
 * @author lanhai
 */
public class SecretUtils {
    private static final String AES = "AES";
    private static final Provider PROVIDER = new BouncyCastleProvider();
    public static final String DEFAULT_SIGN_TYPE = "SHA256WithRSA";
    public static final Integer LENGTH = 2;
    private static final Logger logger = LoggerFactory.getLogger(SecretUtils.class);

    private SecretUtils() {
    }

    public static String sign(PrivateKey privateKey, String text, String signType) {
        SignAlgorithm signAlgorithm = SignAlgorithm.fromSignType(signType);

        try {
            return sign(privateKey, text, signAlgorithm);
        } catch (NoSuchAlgorithmException | SignatureException | InvalidKeyException var5) {
            throw new OpException(var5.getMessage(), var5);
        }
    }

    public static String sign(PrivateKey privateKey, String data, SignAlgorithm signAlgorithm) throws NoSuchAlgorithmException, InvalidKeyException, SignatureException {
        String text = signAlgorithm == SignAlgorithm.SM2 ? data : md5(data);
        Signature signature = Signature.getInstance(signAlgorithm.getAlgorithm(), PROVIDER);
        signature.initSign(privateKey);
        signature.update(text.getBytes(StandardCharsets.UTF_8));
        return Base64.encode(signature.sign());
    }

    public static String htSign(PrivateKey privateKey, String text) {
        try {
            Signature signature = Signature.getInstance("SHA1WithRSA", PROVIDER);
            signature.initSign(privateKey);
            signature.update(text.getBytes(StandardCharsets.UTF_8));
            byte[] data = signature.sign();
            return Base64.encode(data);
        } catch (NoSuchAlgorithmException | SignatureException | InvalidKeyException var4) {
            throw new OpException(var4.getMessage(), var4);
        }
    }

    public static boolean verify(PublicKey publicKey, String text, String sign) {
        return verify(publicKey, text, sign, "SHA256WithRSA");
    }

    public static boolean verify(PublicKey publicKey, String text, String sign, String signType) {
        if (OpenUtils.isEmpty(sign)) {
            return false;
        } else {
            SignAlgorithm signAlgorithm = SignAlgorithm.fromSignType(signType);
            return verify(publicKey, text, sign, signAlgorithm);
        }
    }

    public static boolean verify(PublicKey publicKey, String data, String sign, SignAlgorithm signAlgorithm) {
        String text = signAlgorithm == SignAlgorithm.SM2 ? data : md5(data);

        try {
            Signature signature = Signature.getInstance(signAlgorithm.getAlgorithm(), PROVIDER);
            signature.initVerify(publicKey);
            signature.update(text.getBytes(StandardCharsets.UTF_8));
            return signature.verify(Base64.decode(sign));
        } catch (NoSuchAlgorithmException | SignatureException | InvalidKeyException var6) {
            logger.error("签名验签失败，{}", var6.getMessage(), var6);
            return false;
        }
    }

    public static String md5(String src) {
        String result = "";

        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            result = Base64.encode(md.digest(src.getBytes(StandardCharsets.UTF_8)));
        } catch (Exception var3) {
            logger.error(var3.getMessage(), var3);
        }

        return result;
    }

    public static PrivateKey loadPrivateKey(String alias, String path, String password) {
        try {
            FileInputStream ksfis = new FileInputStream(path);
            Throwable var4 = null;

            PrivateKey var21;
            try {
                KeyStore ks = KeyStore.getInstance("pkcs12", PROVIDER);
                char[] storePwd = password.toCharArray();
                char[] keyPwd = password.toCharArray();
                ks.load(ksfis, storePwd);
                if (OpenUtils.isEmpty(alias)) {
                    Enumeration<String> aliases = ks.aliases();
                    if (aliases.hasMoreElements()) {
                        alias = aliases.nextElement();
                    }
                }

                var21 = (PrivateKey) ks.getKey(alias, keyPwd);
            } catch (Throwable var18) {
                var4 = var18;
                throw var18;
            } finally {
                if (var4 != null) {
                    try {
                        ksfis.close();
                    } catch (Throwable var17) {
                        var4.addSuppressed(var17);
                    }
                } else {
                    ksfis.close();
                }

            }

            return var21;
        } catch (Exception var20) {
            throw new OpException(var20.getMessage(), var20);
        }
    }

    public static PublicKey loadPublicKey(String alias, String path, String password) {
        try {
            FileInputStream ksfis = new FileInputStream(path);
            Throwable var4 = null;

            PublicKey var20;
            try {
                KeyStore ks = KeyStore.getInstance("pkcs12", PROVIDER);
                char[] storePwd = password.toCharArray();
                ks.load(ksfis, storePwd);
                if (OpenUtils.isEmpty(alias)) {
                    Enumeration<String> aliases = ks.aliases();
                    if (aliases.hasMoreElements()) {
                        alias = aliases.nextElement();
                    }
                }

                var20 = ks.getCertificate(alias).getPublicKey();
            } catch (Throwable var17) {
                var4 = var17;
                throw var17;
            } finally {
                if (var4 != null) {
                    try {
                        ksfis.close();
                    } catch (Throwable var16) {
                        var4.addSuppressed(var16);
                    }
                } else {
                    ksfis.close();
                }

            }

            return var20;
        } catch (Exception var19) {
            throw new OpException(var19.getMessage(), var19);
        }
    }

    public static PublicKey loadTlPublicKey(String certPath) {
        try {
            FileInputStream certInputStream = new FileInputStream(certPath);
            Throwable var2 = null;

            PublicKey var5;
            try {
                CertificateFactory certificatefactory = CertificateFactory.getInstance("X.509");
                X509Certificate cert = (X509Certificate) certificatefactory.generateCertificate(certInputStream);
                var5 = cert.getPublicKey();
            } catch (Throwable var15) {
                var2 = var15;
                throw var15;
            } finally {
                if (var2 != null) {
                    try {
                        certInputStream.close();
                    } catch (Throwable var14) {
                        var2.addSuppressed(var14);
                    }
                } else {
                    certInputStream.close();
                }

            }

            return var5;
        } catch (Exception var17) {
            throw new OpException(var17.getMessage(), var17);
        }
    }

    public static String encryptAes(String plainText, String privateKey) {
        try {
            SecretKeySpec secretKeySpec = getSecretKeySpec(privateKey);
            Cipher cipher = Cipher.getInstance("AES");
            byte[] byteContent = plainText.getBytes(StandardCharsets.UTF_8);
            cipher.init(1, secretKeySpec);
            byte[] byteRresult = cipher.doFinal(byteContent);
            StringBuilder sb = new StringBuilder(Constant.INITIAL_CAPACITY);
            int var12 = byteRresult.length;

            for (byte element : byteRresult) {
                String hex = Integer.toHexString(element & 255);
                if (hex.length() == 1) {
                    hex = '0' + hex;
                }

                sb.append(hex.toUpperCase(Locale.ROOT));
            }

            return sb.toString();
        } catch (Exception var16) {
            logger.error("AES加密失败，{} ", var16.getMessage(), var16);
            return plainText;
        }
    }

    public static String decryptAes(String cipherText, String privateKey) {
        try {
            if (cipherText.length() < 1) {
                return null;
            } else {
                byte[] byteRresult = new byte[cipherText.length() / 2];

                for (int i = 0; i < cipherText.length() / LENGTH; ++i) {
                    int high = Integer.parseInt(cipherText.substring(i << 1, (i << 1) + 1), 16);
                    int low = Integer.parseInt(cipherText.substring((i << 1) + 1, (i << 1) + 2), 16);
                    byteRresult[i] = (byte) ((high << 4) + low);
                }

                SecretKeySpec secretKeySpec = getSecretKeySpec(privateKey);
                Cipher cipher = Cipher.getInstance("AES");
                cipher.init(2, secretKeySpec);
                byte[] result = cipher.doFinal(byteRresult);
                return new String(result, StandardCharsets.UTF_8);
            }
        } catch (Exception var10) {
            logger.error("AES解密失败，{} ", var10.getMessage(), var10);
            return cipherText;
        }
    }

    @NotNull
    private static SecretKeySpec getSecretKeySpec(String privateKey) throws NoSuchAlgorithmException {
        KeyGenerator kgen = KeyGenerator.getInstance("AES");
        SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
        random.setSeed(privateKey.getBytes(StandardCharsets.UTF_8));
        kgen.init(128, random);
        SecretKey secretKey = kgen.generateKey();
        byte[] enCodeFormat = secretKey.getEncoded();
        return new SecretKeySpec(enCodeFormat, "AES");
    }

    private enum SignAlgorithm {
        /**
         * SHA256WithRSA
         */
        RSA2("SHA256WithRSA", "SHA256WithRSA"),
        RSA("RSA", "SHA1WithRSA"),
        SM2("SM2", "SM3withSM2");

        private final String signType;
        private final String algorithm;

        SignAlgorithm(String signType, String algorithm) {
            this.signType = signType;
            this.algorithm = algorithm;
        }

        public String getSignType() {
            return this.signType;
        }

        public String getAlgorithm() {
            return this.algorithm;
        }

        public static SignAlgorithm fromSignType(String signType) {
            SignAlgorithm[] var1 = values();
            int var2 = var1.length;

            for (SignAlgorithm item : var1) {
                if (item.getSignType().equals(signType)) {
                    return item;
                }
            }

            return RSA2;
        }
    }
}
